#include "..\include\imp_typedefine.h"
#include "..\include\imp_codec_wrapper.h"
#include "..\include\imp_io_wrapper.h"
#include "..\include\imp_pictext_wrapper.h"

#ifdef IMITV_H263_DEC
#include "..\..\platform\windows\h263codec\include\imp_h263dec.h"
#endif

#include "..\..\part3d\opencore_amr\bin\include\interf_dec.h"
#include "..\..\part3d\opencore_amr\bin\include\interf_enc.h"

#ifdef __cplusplus
extern "C"
{
#endif

#include "..\..\miicodec\bin\include\MiiTypedef.h"
#include "..\..\miicodec\bin\include\miidec.h"
#include "..\..\miicodec\bin\include\miienc.h"

#ifdef __cplusplus
}
#endif

Int32 impcodec_miidec_open(void)
{
#ifdef IMITV_H263_DEC
	return (Int32)h263dec_open( 0, 1, 1 );
#else
	return (Int32)miidec_open(0, 1);
#endif
}

Int32 impcodec_miidec_decode(Int32 handle, const Int8* input, Int32 bytes, Int32 *availble)
{
#ifdef IMITV_H263_DEC
	Int32 eat = (Int32)h263dec_decode((void*)handle, (const void*)input, (int)bytes, (int*)availble);
#else
	Int32 eat = (Int32)miidec_decode((void*)handle, (const void*)input, (int)bytes, (int*)availble);
#endif
	return eat;
}

const void *impcodec_miidec_picture(Int32 handle,Int8* buffer)
{
#ifdef IMITV_H263_DEC
	h263dec_picture((void*)handle, (void*)buffer);
#else
	miidec_picture((void*)handle, (void*)buffer);
#endif
	return (const void*)buffer;
}
void impcodec_miidec_size(Int32 handle, Int32 *width, Int32 *height,Int32* size)
{
#ifdef IMITV_H263_DEC
	h263dec_size((void*)handle, (int*)width, (int*)height, (int*)size);
#else
	miidec_size((void*)handle, (int*)width, (int*)height, (int*)size);
#endif
}
void impcodec_miidec_close(Int32 handle)
{
#ifdef IMITV_H263_DEC
	h263dec_close((void*)handle);
#else
	miidec_close((void*)handle);
#endif
}

typedef struct
{
	void *state;
	Mode mode;
}t_ime_audenc, t_ime_auddec;

Int32 impcodec_amrdec_open(void)
{
	t_ime_auddec *inst = (t_ime_auddec *)IMP_Malloc( sizeof(t_ime_auddec) );
	inst->state = Decoder_Interface_init();
	return (Int32)inst;
}

void impcodec_amrdec_decode(Int32 inst, Int8 *input, Int8 *output)
{
	t_ime_auddec *hdl = (t_ime_auddec *)inst;
	Decoder_Interface_Decode(hdl->state, (unsigned char *)input, (short*)output, 0);
}

void impcodec_amrdec_close(Int32 inst)
{
	t_ime_auddec *hdl = (t_ime_auddec *)inst;
	Decoder_Interface_exit(hdl->state);
	IMP_Free( hdl );
}
Int32 impcodec_miienc_open(Int32 w, Int32 h, Int32 fms, Int32 bitrate)
{
	

#if (defined(MII_ANDROID_PLATFORM) || defined(WINCE))
	Int32 henc = (Int32)mii_exea(w,h,32,1000/fms, 30);
#else
	Int32 henc = (Int32)mii_exea(w,h,40,1000/fms, 30);
#endif
	return henc;
}

Int32 impcodec_miienc_encode(Int32 handle, const Int8* input, Int8* output, Int32* length, Int32* keyframe)
{
//	return (Int32)miienc_encode((void *)handle, (const char*)input, (void*)output, (int*)length, (int*)keyframe);
	return (Int32)mii_exeb((void *)handle, (const void*)input, (void*)output, (int*)length, (int*)keyframe);
}
void impcodec_miienc_close(Int32 handle)
{
//	miienc_close((void *)handle);
	mii_exec((void*)handle);
}

Int32 impcodec_amrenc_open(Int32 mode)
{
	t_ime_audenc *inst = new t_ime_audenc;
	inst->mode = MR515;
	inst->state =	(Int32 *)Encoder_Interface_init(0);
	return (Int32)inst;
}

Int32 impcodec_amrenc_encode(Int32 inst, Int8 *input, Int8 *output)
{
	Int32 size;
	t_ime_audenc *hdl = (t_ime_audenc *)inst;
	size = Encoder_Interface_Encode(hdl->state, hdl->mode, (short*)input, (unsigned char*)output, 0);
	return size;
}
void impcodec_amrenc_close(Int32 inst)
{
	t_ime_audenc *hdl = (t_ime_audenc *)inst;
	Encoder_Interface_exit(hdl->state);
	delete hdl;
}

#define COLOR24_TO_16(x) ((((x)>>8) & 0xf800) | (((x)>>5) & 0x07e0) | (((x)>>3) & 0x001f))

/*jpeg decoding*/
extern "C" void ime_CC_RGB32toYV12_C( unsigned char *RGBBuffer, int ImageWidth, int ImageHeight,
                       unsigned char *YBuffer, unsigned char *UBuffer, unsigned char *VBuffer, int SrcPitch,int DstPitch );

void impmm_jpeg_decode(Int8* jpeg_data, Int32 jpeg_len, Int8 *yuv_buf, Int32 *w, Int32 *h)
{
	Int32 inst = impict_jpeg_init();
	Int8 *rgb24_buf;
	if(impict_jpeg_decode(inst, jpeg_data, jpeg_len, &rgb24_buf, (Int32*)w, (Int32*)h))//RGB out_mode
	{
		Int32 i,j;
		Int32 w1 = *w, h1 = *h;
		Int32 size = w1*h1;
		Int8 *buf_y = (Int8*)yuv_buf;
		Int8 *buf_u = buf_y + size;
		Int8 *buf_v = buf_u + size/4;
		ime_CC_RGB32toYV12_C((UInt8*)rgb24_buf, w1, h1, (UInt8*)buf_y, (UInt8*)buf_u, (UInt8*)buf_v, w1*3, w1);
	}
	impict_jpeg_deinit(inst);
}

static Int32 produce_jpeg_data(Int8 *jpeg)
{
	static Int32 index=0;
	Int8 filename[50];

	index = (index+1)%10;
	IMP_Sprintf(filename, "e:\\work\\jpeg\\%d.jpg", index);
	ImpFileHandle fp = IMP_FileOpen(filename, "rb");
	IMP_FileSeek(fp, 0, IMPFile_Seek_End);
	Int32 size = IMP_FileTell(fp);
	IMP_FileSeek(fp, 0, IMPFile_Seek_Begin);
	IMP_FileRead(jpeg, size, fp);
	IMP_FileClose(fp);

	return size;
}


void impmm_jpeg_encode(Int8 *yuv_buf, Int32 w, Int32 h, Int8 *out_buf, Int32 *out_len)
{
	*out_len = produce_jpeg_data(out_buf);
}